package stud.mpgame.flash.scene;

import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.Lib;
import stud.mpgame.flash.game.GameEventDispatcher;

import flash.events.ProgressEvent;
import flash.events.MouseEvent;

import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;

import stud.mpgame.network.NetworkMonitor;
import stud.mpgame.network.Message;
import stud.mpgame.network.MessageDescription;

import stud.mpgame.network.service.time.TimeService;

import stud.mpgame.snapshot.ISnapshot;
import stud.mpgame.snapshot.SnapshotManager;

import stud.mpgame.flash.IScene;

import stud.mpgame.flash.test.TestSnapshot;

import stud.mpgame.flash.net.description.TestCommandDescription;
import stud.mpgame.flash.net.description.TestSnapshotDescription;
import stud.mpgame.flash.net.description.GameWorldMessageDescription;

import stud.mpgame.flash.game.ArrowKeyListener;

import stud.mpgame.flash.net.command.TestCommand;

import stud.mpgame.flash.game.GameWorld;

import stud.mpgame.flash.game.Player;

import org.aswing.JLabel;
import org.aswing.ASFont;
import org.aswing.ASColor;
import org.aswing.geom.IntPoint;
import org.aswing.geom.IntDimension;
import stud.mpgame.network.service.ping.PingNotificationMessageDescription;
import stud.mpgame.network.service.ping.PingNotificationUserObject;

/**
 * ...
 * @author GreK
 */
class GameScene extends Sprite, implements IScene {	
	
	public static inline var NAME = "GameScene";
	
	private var networkMonitor:NetworkMonitor;
	private var snapshotManager:SnapshotManager;
	private var timeService:TimeService; //temporary, for logs
	
	private var gameWorldView:GameWorldView;
	private var gameEventDispatcher:GameEventDispatcher;
	
	private var valueField:TextField;
	private var sendButton:TextField;
	private var snapshotField:TextField;
	private var arrowKeyListener:ArrowKeyListener;
	
	public function new() {
		super();
	}
	
	
	private function handleSendClick(e:MouseEvent) {
		//trace("KEY PRESSED TIME: " + timeService.getServerTime() + "LocalSS Time = " + snapshotManager.getLocalSnapshot().getTime());
		var command:TestCommand = new TestCommand(timeService.getServerTime(), Std.parseInt(valueField.text));
		snapshotManager.addCommand(command);
		//trace("CMD:" + snapshotManager.getLocalSnapshotTime() + "; " + timeService.getServerTime());
		
		var message:Message = new Message(networkMonitor, TestCommandDescription.getInstance());
		message.putUserObject(command);
		message.send();
	}
	
	private function gameWorldReceived(message:Message) {
		//trace("RECEIVED");
		var gameWorld:GameWorld = cast(message.getUserObject(GameWorld), GameWorld);
		snapshotManager.addServerSnapshot(gameWorld);
	}	
	
	public function getName():String {
		return NAME;
	}
	
	public function init(data:Dynamic):Void {
		this.networkMonitor = data.networkMonitor;
		this.snapshotManager = data.snapshotManager;
		this.timeService = data.timeService;
		
		this.gameEventDispatcher = data.gameEventDispatcher;
		
		this.gameWorldView = data.gameWorldView;
		
		gameWorldView.scaleX = gameWorldView.scaleY = 0.5;
		addChild(gameWorldView);

		gameEventDispatcher.addGameEventListener(GameEvent.playerAdded, playerAdded);
        gameEventDispatcher.addGameEventListener(GameEvent.playerRemoved, playerRemoved);		
		
		arrowKeyListener = new ArrowKeyListener(networkMonitor, timeService, snapshotManager);
		
		MessageDescription.registerDescription(TestSnapshotDescription.getInstance());
		MessageDescription.registerDescription(TestCommandDescription.getInstance());
		MessageDescription.registerDescription(GameWorldMessageDescription.getInstance());
		
		//TODO uncomment!
		networkMonitor.getMessageDispatcher().addMessageReceivedListener(GameWorldMessageDescription.getInstance(), gameWorldReceived);
		
		var pingLabel:JLabel = new JLabel("PING: N/A", null, 2);
		pingLabel.setFont(new ASFont("Tahoma", 24, true));
		pingLabel.setForeground(ASColor.RED);
		pingLabel.setSize(new IntDimension(200, 30));
		pingLabel.x = 100;
		addChild(pingLabel);
		var pingTime = Lib.getTimer();
		
		networkMonitor.getMessageDispatcher().addMessageReceivedListener(
			PingNotificationMessageDescription.getInstance(), 
			function(message:Message):Void {
				var pingNotificationUserObject:PingNotificationUserObject = 
					cast(message.getUserObject(PingNotificationUserObject), PingNotificationUserObject);
				var ping:Int = pingNotificationUserObject.getPing();

				if ( Lib.getTimer() >= pingTime ) 
				{
					pingTime += 1000;
					//ping += (10 - Std.random(20));
					pingLabel.setText("PING: " + ping);
				}
			});
	}
	
	public function clear():Void {
		MessageDescription.unRegisterDescription(TestSnapshotDescription.getInstance());
		MessageDescription.unRegisterDescription(TestCommandDescription.getInstance());
		MessageDescription.unRegisterDescription(GameWorldMessageDescription.getInstance());
		
		networkMonitor.getMessageDispatcher().removeMessageReceivedListener(GameWorldMessageDescription.getInstance(), gameWorldReceived);
		
		arrowKeyListener.clear();
	}
	
	public function update(deltaTime:Int):Void {
		if (snapshotManager == null)
			return;
		var snapshot:ISnapshot = snapshotManager.update(deltaTime);
		//trace("AFTER UPDATE: ");
		//cast(snapshot, GameWorld).toString();
		gameWorldView.updateWorld(cast(snapshot, GameWorld));
		//trace("LOCAL SS TIME = " + snapshot.getTime() + " SERVER TIME = " + timeService.getServerTime());
	}
	
    public function playerAdded(e:GameEvent, player:Player) {
		gameWorldView.addPlayer(player);
	}
	
	public function playerRemoved(e:GameEvent, player:Player) {
		gameWorldView.removePlayer(player);
	}	
	
	public function getContentRoot():DisplayObject {
		return this;
	}
}